home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 5235 < prev    next >
Encoding:
Text File  |  1996-08-05  |  8.5 KB  |  239 lines

  1. Path: fohnix.metronet.com!not-for-mail
  2. From: milam@fohnix.metronet.com (Stan Milam)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: embedded strtok() calls on different strings?
  5. Date: 8 Feb 1996 20:57:58 -0600
  6. Organization: Texas Metronet, Inc  (login info (214/488-2590 - 817/571-0400))
  7. Message-ID: <4fed7m$sk2@fohnix.metronet.com>
  8. References: <DMGrn7.1Bx0@CompStar.bnr.ca>
  9. NNTP-Posting-Host: fohnix.metronet.com
  10. X-Newsreader: TIN [version 1.2 PL2]
  11.  
  12. tzinck@bnr.ca wrote:
  13.  
  14. : Hello.
  15.  
  16.  
  17. : I want to do the following:
  18.  
  19.  
  20. : char *string1="This is string one";
  21. : char *string2="This is string two";
  22.  
  23. : void *vp1;
  24. : void *vp2;
  25.  
  26. : vp1 = strtok(string1," ");
  27.  
  28. : while (vp1 != NULL){
  29. :     printf("Tok1 = %s\n", (char *) vp1);
  30.  
  31. :     vp2 = strtok(string2," ");
  32. :     while (vp2!=NULL){
  33. :         printf("Tok2 = %s\n", (char *) vp2);
  34. :         vp2 = strtok(NULL, " ");
  35. :     }
  36.  
  37. :     vp1 = strtok(NULL, " ");
  38. : }
  39.  
  40. : But the output is :
  41. : Tok1 = This
  42. : Tok2 = This
  43. : Tok2 = is
  44. : Tok2 = string
  45. : Tok2 = two
  46.  
  47.  
  48. : as vp1 gets corrupted. Any thoughts ?
  49.  
  50. : -Tom
  51. :     
  52.  
  53. Why yes.  The strtok() function uses an internal static pointer to the initial 
  54. string used in the very first call.  All subsequent calls to strtok() use
  55. this pointer to find the next token and this continues until all tokens
  56. are exhausted *OR* strtok() is called with a new string.  When this happens
  57. the internal pointer now points to the new string with no way to get back
  58. to the first one you started with.  So, what you are trying to accomplish 
  59. cannot be done with strtok().
  60.  
  61. Also, strtok() does not handle empty tokens very well.  Here are a couple
  62. of alternative solutions to strtok() that I have come up with.  I really
  63. like strptok() the best.  Enjoy!
  64.  
  65. Regards,
  66. Stan Milam.
  67.  
  68. /**********************************************************************/
  69. /* File Id:                     strparse.c.                           */
  70. /* Author:                      Stan Milam.                           */
  71. /* Date Written:                20-Feb-1995.                          */
  72. /* Description:                                                       */
  73. /*     The str_parse() function is used to extract fields from de-    */
  74. /*     limited ASCII records. It is designed to deal with empty fields*/
  75. /*     in a logical manner and meant to preclude the use of strtok()  */
  76. /*     for such purposes!                                             */
  77. /*                                                                    */
  78. /* Arguments:                                                         */
  79. /*     char **str       - The address of a pointer which in turn      */
  80. /*                        points to the string being parsed. The      */
  81. /*                        actual pointer is modified with each call to*/
  82. /*                        point to the beginning of the next field.   */
  83. /*     char *delimiters - The address of the string containing the    */
  84. /*                        characters used to delimit the fields within*/
  85. /*                        the record.                                 */
  86. /*                                                                    */
  87. /* Return Value:                                                      */
  88. /*     A pointer of type char which points to the current field in the*/
  89. /*     parsed string.  If an empty field is encountered the address   */
  90. /*     is that of an empty string (i.e. "" ). When there are no more  */
  91. /*     fields in the record a NULL pointer value is returned.         */
  92. /*                                                                    */
  93. /**********************************************************************/
  94.  
  95. #include <stddef.h>
  96. #include <string.h>
  97.  
  98. char *str_parse( char **str, char *delimiters ) {
  99.  
  100.     char *head, *tail, *rv;
  101.  
  102.     if ( *str == NULL || **str == '\0' )
  103.         rv = NULL;
  104.     else if ( delimiters == NULL || *delimiters == '\0' )
  105.         rv = NULL;
  106.     else {
  107.         rv = head = *str;
  108.         if ( ( tail = strpbrk( head, delimiters ) ) == NULL )
  109.             *str = head + strlen( head );
  110.         else {
  111.             *tail = '\0';
  112.             *str = tail + 1;
  113.         }
  114.     }
  115.     return rv;
  116. }
  117.  
  118. #ifdef TEST
  119. #include <stdio.h>
  120. #include <assert.h>
  121.  
  122. int main( void ) {
  123.  
  124.     char *wrk, *rv;
  125.     char delimiters[] = ":;";
  126.     char wrkstr[] = "1:2::4:;6:7";
  127.  
  128.     wrk = "";
  129.     assert( str_parse( NULL, delimiters ) == NULL );
  130.     assert( str_parse( &wrk, delimiters ) == NULL );
  131.  
  132.     wrk = wrkstr;
  133.     assert( str_parse( &wrk, NULL ) == NULL );
  134.     assert( str_parse( &wrk, "" ) == NULL );
  135.  
  136.     while((rv = str_parse( &wrk, delimiters )))
  137.         puts( rv );
  138.  
  139.     return 0;
  140. }
  141. #endif
  142.  
  143.  
  144. /*FILE*****************************************************************/
  145. /* File Id:                    strptok.c.                             */
  146. /* Author:                     Stan Milam.                            */
  147. /* Date Written:               25-Apr-95.                             */
  148. /* Description:                                                       */
  149. /*     Implement a strtok() like function which preserves the original*/
  150. /*     string.                                                        */
  151. /*                                                                    */
  152. /*****************************************************************FILE*/
  153.  
  154. #include <stddef.h>
  155. #include <string.h>
  156.  
  157. /*FUNCTION*************************************************************/
  158. /* Name: strptok().                                                   */
  159. /*                                                                    */
  160. /* Description:                                                       */
  161. /*     This function implements a strtok() like function which pre-   */
  162. /*     serves the original string and copies tokens into a programmer */
  163. /*     supplied buffer.                                               */
  164. /*                                                                    */
  165. /* Arguments:                                                         */
  166. /*     char *dest - Address of buffer where token is to be copied.    */
  167. /*     char *src  - Address of source buffer where tokens are to be   */
  168. /*                  extracted.                                        */
  169. /*     char *brk  - "Break" characters which delimit tokens.          */
  170. /*                                                                    */
  171. /* Return Value:                                                      */
  172. /*     NULL when the end of the string is encounted or when the src   */
  173. /*     argument is NULL or empty.  Otherwise the address just beyond  */
  174. /*     the last token found in the source string.                     */
  175. /*                                                                    */
  176. /*************************************************************FUNCTION*/
  177.  
  178. char *strptok( char *dest, char *src, char *brk ) {
  179.  
  180.     unsigned len;
  181.     char *rv, *wrk;
  182.  
  183.     /******************************************************************/
  184.     /* Make sure destination is empty and check for a valid source.   */
  185.     /******************************************************************/
  186.  
  187.     dest[0] = '\0';
  188.     if ( src == NULL || *src == '\0' )
  189.         rv = NULL;
  190.  
  191.     /******************************************************************/
  192.     /* If there are not any break characters set rv to NULL and copy  */
  193.     /* the remaining characters to the destination.                   */
  194.     /******************************************************************/
  195.  
  196.     else if (( wrk = strpbrk(src, brk) ) == NULL) {
  197.         rv = NULL;
  198.         strcpy( dest, src );
  199.     }
  200.     
  201.     /******************************************************************/
  202.     /* If the first character of source is a break character then     */
  203.     /* skip over it.                                                  */
  204.     /******************************************************************/
  205.  
  206.     else if ( src == wrk )
  207.         rv = src + 1;
  208.  
  209.     /******************************************************************/
  210.     /* Found a token! Compute return value, length of token and copy  */
  211.     /* it to destination making sure it is null terminated.           */
  212.     /******************************************************************/
  213.  
  214.     else {
  215.         rv = wrk + 1;
  216.         len = wrk - src;
  217.         strncpy( dest, src, len )[len] = '\0';
  218.     }
  219.     return rv;
  220. }
  221.  
  222. #ifdef TEST
  223. #include <stdio.h>
  224. int main( void ) {
  225.  
  226.     char dest[50] = "", *rv;
  227.     char *src = ":tsdsstm:243::0:Stan Milam,3730442330,Y:/u/tsdsstm/ksh";
  228.  
  229.     rv = strptok( dest, NULL, ":" );
  230.     rv = strptok( dest, "",   ":" );
  231.  
  232.     rv = strptok( dest, src, ":" );
  233.     while ( rv || dest[0] ) {
  234.         printf(":%s:\n", dest);
  235.         rv = strptok( dest, rv, ":" );
  236.     }
  237. }
  238. #endif
  239.